Skip to content

feat: support WebDAV backup#181

Open
opoojkk wants to merge 3 commits into
prem-k-r:mainfrom
opoojkk:main
Open

feat: support WebDAV backup#181
opoojkk wants to merge 3 commits into
prem-k-r:mainfrom
opoojkk:main

Conversation

@opoojkk

@opoojkk opoojkk commented Apr 17, 2026

Copy link
Copy Markdown

📌 Description

This PR adds WebDAV backup support to MYNT and refines the overall cloud backup flow.

What’s included

  • Added a dedicated Cloud Backup section in Settings for WebDAV configuration
  • Added Backup to WebDAV and Restore Latest actions
  • Added support for automatic scheduled backups to WebDAV
  • Introduced a shared snapshot service to unify local backup/export and cloud backup/restore logic
  • Added required browser permissions for:
    • downloads support for backup file export
    • optional host permissions for user-provided WebDAV servers
  • Added localization support for the new WebDAV/cloud backup UI across existing language files
  • Updated styling for the new backup panel, including responsive and dark theme support

Why

This allows users to back up and restore their MYNT settings through their own WebDAV storage instead of relying only on manual local JSON export/import.

🎨 Visual Changes (Screenshots / Videos)

  • Added a new Cloud Backup section under Settings
  • Added WebDAV URL / username / password inputs
  • Added manual backup / restore buttons
  • Added automatic backup toggle and interval input
Snipaste_2026-04-17_20-44-18

🔗 Related Issues

  • Closes #<issue_number>
  • Related to #<issue_number>

✅ Checklist

  • I have read and followed the Contributing Guidelines.
  • My code follows the project's coding style and conventions.
  • I have tested my changes thoroughly to ensure expected behavior.
  • I have verified compatibility across Chrome and Firefox (additional browsers if applicable).
  • I have attached relevant visual evidence (screenshots/videos) if applicable.
  • I have updated the CHANGELOG.md under the appropriate categories with all my changes in this PR.

Overview

This PR introduces WebDAV backup and restore functionality to MaterialYouNewTab, enabling users to securely back up their settings to their own WebDAV storage servers. It establishes a unified snapshot architecture for managing backup/restore operations and expands localization support to 32 languages, including the newly added Swedish.

Core Functionality

Snapshot Service (scripts/snapshot-service.js)

  • New module providing centralized backup/restore logic for local and cloud scenarios
  • Captures localStorage and selected IndexedDB stores (currently ImageDBbackgroundImages)
  • Validates, normalizes, and deserializes snapshot payloads
  • Handles Blob serialization to data URLs for storage/transmission

WebDAV Cloud Backup (scripts/backup-restore.js)

  • Manual backup/restore: Upload/download snapshots to/from WebDAV servers via PUT/MKCOL HTTP requests
  • Automatic scheduled backups: Configurable interval-based backups with timezone-aware scheduling
  • Host permission management: Runtime permission checks using chrome.permissions/browser.permissions APIs
  • Latest backup tracking: Maintains *_latest.json pointer files for quick restore discovery
  • Error handling: Validation for missing WebDAV configuration and permission denials

Settings UI (index.html, style.css)

  • New "Cloud Backup" section with WebDAV Sync subsection
  • WebDAV URL, username, and password input fields
  • Manual "Backup to WebDAV" and "Restore Latest" action buttons
  • Automatic backup toggle with configurable interval (in hours)
  • Responsive design with dark theme support
  • Extensive CSS class additions for layout, typography, and interactive elements

Localization & Language Support

  • 32 Languages: Added complete translation coverage for WebDAV/cloud backup UI across 30+ existing locales plus new Swedish support
  • New Swedish Locale (locales/sv.js): Full translation set with regional formatting
  • Translation Keys: Consistent new keys across all locales (cloudBackupSectionTitle, webdavTitle, webdavUrlPlaceholder, saveBackupConfig, webdavMissingConfig, webdavPermissionDenied, etc.)
  • Language Script Updates (scripts/languages.js): Swedish added to supported language tables; localized date formatting and New Tab title support added

Manifest & Permissions

  • Version: Bumped from 3.3.6 to 3.3.7
  • New Permissions:
    • Added "downloads" to required permissions (for backup file exports)
    • Added optional host permissions for http://*/* and https://*/* (for user-provided WebDAV servers)

Related Changes

  • Swedish Language Support: Added to all relevant lookup tables (translations, menuWidths, decimal separators, clock date formatting, weather humidity sliders)
  • Language Analysis Tool (tools/languagesAnalysis.html): Updated to include Swedish locale validation
  • Accessibility: Weather and location icon drag behavior disabled (draggable="false")
  • Documentation: README updated with Swedish language entry and additional translator credits for Ukrainian and Hungarian

Technical Architecture

The PR refactors backup logic from inline implementations to a service-based model where:

  1. snapshotService handles snapshot creation, validation, and restoration
  2. backup-restore.js orchestrates local exports and WebDAV cloud operations
  3. UI event handlers delegate to shared utility functions (loadWebDAVSettings(), setupAutoBackupScheduler(), applyStorageTexts())
  4. Automatic backups run on a timer with minimum interval enforcement and non-interactive permission checks

Browser Compatibility

Changes are compatible with both Chrome (via chrome.permissions) and Firefox (via browser.permissions) with conditional API usage patterns maintained.

feat: support WebDAV backup
@coderabbitai

coderabbitai Bot commented Apr 17, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds WebDAV cloud backup/restore and automatic scheduled backups using a new in-page snapshot service; refactors backup/restore to use snapshots; updates UI and styles for cloud backup settings; adds Swedish locale and many translated strings; and expands extension permissions for downloads and optional host access.

Changes

Cohort / File(s) Summary
Manifest & Permissions
manifest.json, manifest(firefox).json
Bumped version to 3.3.7, added "downloads" permission and optional host permissions for http://*/* and https://*/*.
Snapshot Service
scripts/snapshot-service.js
New global window.snapshotService providing create/restore/validate/normalize snapshot APIs for localStorage and IndexedDB (Blob serialization/deserialization) and data-clearing utilities.
Core Backup Logic
scripts/backup-restore.js
Reworked backup/restore to use snapshotService; added WebDAV upload/download (PUT/GET/MKCOL), _latest.json pointer handling, host permission checks, Basic Auth header handling, and an automatic backup scheduler with persisted settings.
UI & Styling
index.html, style.css, scripts/languages.js
Added Cloud Backup UI (WebDAV settings, backup/restore buttons, auto-backup controls), deferred loading of snapshot-service script, ~35 new CSS classes and dark-theme overrides, and language wiring for new translation keys including Swedish.
Localization
locales/sv.js, locales/hu.js, locales/uk.js, locales/en.js, locales/* (many locales/*.js files)
Added Swedish locale and added/updated cloud backup & WebDAV-related translation keys across many locale files (newTabTitle in several locales plus ~20 new keys per language).
Backup UI Behavior & Misc
scripts/clock.js, scripts/search.js, scripts/weather.js, tools/languagesAnalysis.html
Minor language/UX wiring: added sv to date/slider mappings, safer optional-chaining in search hints, and included sv in analysis tooling.
Docs & Changelog
CHANGELOG.md, README.md, .github/pull_request_template.md
Changelog entry for WebDAV backup/restore; README language list updates (added Swedish, Hungarian translator update); PR template extended with AI-assistance checklist.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as Browser UI
    participant SnapshotSvc as window.snapshotService
    participant Storage as Local Storage / IndexedDB
    participant WebDAV as WebDAV Server

    rect rgba(100,200,100,0.5)
    Note over User,WebDAV: Manual WebDAV Backup
    User->>UI: Click "Backup to WebDAV"
    UI->>SnapshotSvc: createSnapshot()
    SnapshotSvc->>Storage: export localStorage / IndexedDB
    Storage-->>SnapshotSvc: snapshot data
    SnapshotSvc-->>UI: snapshot object
    UI->>WebDAV: PUT snapshot_<ts>.json (with Basic Auth)
    WebDAV-->>UI: 200 OK
    UI->>WebDAV: PUT snapshot_latest.json (pointer)
    WebDAV-->>UI: 200 OK
    UI-->>User: show success
    end

    rect rgba(100,150,200,0.5)
    Note over User,WebDAV: Manual WebDAV Restore
    User->>UI: Click "Restore Latest"
    UI->>WebDAV: GET snapshot_latest.json
    WebDAV-->>UI: latest filename
    UI->>WebDAV: GET snapshot_<ts>.json
    WebDAV-->>UI: snapshot payload
    UI->>SnapshotSvc: normalizeSnapshot() + validateSnapshot()
    SnapshotSvc-->>UI: validated snapshot
    UI->>SnapshotSvc: restoreSnapshot()
    SnapshotSvc->>Storage: clear and write localStorage / IndexedDB
    Storage-->>SnapshotSvc: complete
    SnapshotSvc-->>UI: success
    UI->>UI: reload page
    end

    rect rgba(200,100,100,0.5)
    Note over UI,WebDAV: Automatic Scheduled Backup
    Note over UI: Timer fires per saved interval
    UI->>SnapshotSvc: createSnapshot()
    SnapshotSvc-->>UI: snapshot
    UI->>UI: ensureHostPermission()
    alt permission granted
        UI->>WebDAV: PUT files (non-interactive)
        WebDAV-->>UI: success
    else permission denied
        UI-->>User: log/skip upload
    end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

i18n/l10n

Suggested reviewers

  • prem-k-r
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: support WebDAV backup' clearly describes the main change - adding WebDAV backup functionality. It is concise, specific, and directly related to the primary objective of the changeset.
Description check ✅ Passed The PR description follows the template structure with all major sections completed: clear description of changes, visual evidence provided, checklist items marked, and CHANGELOG updates confirmed. The description comprehensively explains what was added and why.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/languages.js (1)

244-256: ⚠️ Potential issue | 🟡 Minor

Remove unused cloudPrefixPlaceholder from all locale files or implement the missing wiring.

All 30 locale files define cloudPrefixPlaceholder, but it is never referenced in the codebase. There is no input element in index.html for a cloud prefix configuration, and no entry in placeholderMap to wire it up. Either remove this dead code from the locales or implement the missing feature (input element + placeholderMap entry).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/languages.js` around lines 244 - 256, Locale key
cloudPrefixPlaceholder is defined but unused; either remove it from all locale
files or wire it into the UI by adding a corresponding input in index.html and
mapping it in scripts/languages.js's placeholderMap. To implement the feature:
add an input element for the cloud prefix in index.html with an id (e.g.,
"cloudPrefixInput"), then add { id: "cloudPrefixInput", key:
"cloudPrefixPlaceholder" } to the placeholderMap array in scripts/languages.js
so loadPlaceholders/getPlaceholder logic applies; alternatively, delete the
cloudPrefixPlaceholder entries from all locale JSONs if the feature is not
needed.
🧹 Nitpick comments (8)
CHANGELOG.md (1)

21-21: Consider adding author attribution and PR link.

Every other entry under [Unreleased] → Added (and prior releases) includes ([@author]) and ([#PR]) references. This new entry omits both.

✏️ Suggested edit
-- Added WebDAV backup and restore support, including manual cloud backup and restore for MYNT settings.
+- Added WebDAV backup and restore support, including manual cloud backup and restore for MYNT settings ([`@opoojkk`](https://github.com/opoojkk)) ([`#181`](https://github.com/prem-k-r/MaterialYouNewTab/pull/181))

Also, the PR description mentions automatic scheduled backups support, which is not reflected in this changelog entry.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CHANGELOG.md` at line 21, Update the CHANGELOG entry that currently reads
"Added WebDAV backup and restore support, including manual cloud backup and
restore for MYNT settings." to include the author and PR attribution in the same
format as other entries (e.g., "([`@author`]) ([`#PR`])") and extend the text to
mention automatic scheduled backups support (e.g., "...including manual and
automatic scheduled cloud backups and restore for MYNT settings."), keeping
punctuation and style consistent with other [Unreleased] → Added items.
manifest.json (1)

8-15: Redundant specific host entries under optional_host_permissions.

With http://*/* and https://*/* now declared, the specific endpoints on lines 11–14 (google.com/complete/search, duckduckgo.com/ac, search.brave.com/api/suggest, *.wikipedia.org/...) are strict subsets and have no additional effect. They can be removed to simplify the manifest, or — preferably — the wildcards should be removed and the WebDAV host added via permissions.request({ origins: [...] }) at runtime from the user-supplied URL (which ensureHostPermission in scripts/backup-restore.js:332-352 already supports), avoiding a full-web optional grant.

Up to you whether to prioritize simplicity (keep wildcards, drop specifics) or minimal permissions (drop wildcards, keep specifics and request WebDAV origin dynamically).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@manifest.json` around lines 8 - 15, The manifest currently declares both
broad wildcards in optional_host_permissions and redundant specific origins (the
google/duckduckgo/brave/wikipedia endpoints); choose one approach and update
optional_host_permissions accordingly: either keep the wildcards (http://*/* and
https://*/*) and remove the specific endpoint entries to simplify the manifest,
or remove the global wildcards and keep only the necessary specific origins and
handle the WebDAV origin at runtime by calling permissions.request({ origins:
[...] }) via the existing ensureHostPermission logic in
scripts/backup-restore.js so you don't require full-web optional grants.
index.html (2)

1897-1898: No upper bound on interval input.

min="1" but no max, so users can enter enormous values (e.g., millions of hours). Consider a reasonable cap (e.g., max="720" for 30 days) to prevent accidental scheduling of effectively-never backups.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.html` around lines 1897 - 1898, The number input with id
"cloudIntervalInput" (class "webdavInput webdavIntervalInput") currently has
min="1" but no upper bound; add a sensible max (e.g., max="720") to the input
and enforce the same limit in any client-side validation logic that reads/sets
this field (validate in the form submit handler or the function that processes
cloudIntervalInput to clamp or reject values > max), and update any
placeholder/help text if necessary to reflect the allowed range.

1871-1872: Add autocomplete hints to credential inputs.

The password input has no autocomplete attribute; add autocomplete="current-password" (and autocomplete="username" on the username field) so browsers and password managers behave correctly, or autocomplete="off" if you explicitly don't want them saved for this WebDAV-server config.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.html` around lines 1871 - 1872, The password input with id
"webdavPasswordInput" is missing an autocomplete hint; add
autocomplete="current-password" to that element and also add
autocomplete="username" to the corresponding username input (the WebDAV username
input element, e.g., the element with id like "webdavUsernameInput" or the
form's username input) so browsers and password managers can store/fill
credentials correctly (or use autocomplete="off" on both if you intentionally
want to disable saving).
locales/fa.js (1)

224-243: Minor: property-key quoting style inconsistent with rest of file.

The rest of this file uses unquoted property names (e.g., github:, feedback:), but the new keys are quoted ("cloudBackupSectionTitle":). Functionally identical, but consider matching the existing style for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@locales/fa.js` around lines 224 - 243, Change the newly added quoted object
keys to the unquoted style used elsewhere in the file: replace
"cloudBackupSectionTitle", "webdavTitle", "webdavBackupText",
"webdavRestoreText", "webdavUrlPlaceholder", "cloudPrefixPlaceholder",
"webdavUsernamePlaceholder", "webdavPasswordPlaceholder", "cloudAutoBackupText",
"cloudIntervalPlaceholder", "cloudIntervalHours", "saveBackupConfig",
"backupConfigSaved", "webdavMissingConfig", "webdavPermissionDenied",
"webdavBackupCompleted", "webdavDownloadFailed", "webdavUploadFailed",
"webdavRestoreConfirm", and "webdavLatestPointerMissing" so they appear without
surrounding quotes (e.g., cloudBackupSectionTitle:) and preserve the exact
string values and commas to keep the object valid.
scripts/snapshot-service.js (2)

196-212: openDatabase rejects with a generic message, losing diagnostic detail.

request.onerror = () => reject(new Error("Database error.")) discards request.error, which in turn is what bubbles up to the user via webdavUploadFailed / restorefailed. Forwarding the underlying error gives much better debugging info:

-            request.onerror = () => reject(new Error("Database error."));
+            request.onerror = () => reject(request.error || new Error("Database error."));

Also consider handling request.onblocked (another state that can stall the upgrade path).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/snapshot-service.js` around lines 196 - 212, The openDatabase promise
currently rejects with a generic Error in request.onerror, losing diagnostic
info; change request.onerror to reject with the underlying IndexedDB error (use
request.error or event.target.error) so callers (e.g.,
webdavUploadFailed/restorefailed) get the real cause, and add a
request.onblocked handler that rejects or rejects with a specific "blocked"
Error (or logs and rejects) to surface upgrade blocking conditions; locate these
handlers in the openDatabase function (request.onerror, request.onblocked) and
update them accordingly.

214-221: Redundant condition in isTransientLocalStorageKey.

key.startsWith("quotes_") already matches "quotes_metadata_timestamp", so the explicit equality check is dead code.

     return key.startsWith("quotes_")
-        || key === "quotes_metadata_timestamp"
         || key === "weatherParsedData"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/snapshot-service.js` around lines 214 - 221,
isTransientLocalStorageKey contains a redundant check: key.startsWith("quotes_")
already covers "quotes_metadata_timestamp", so remove the explicit equality
branch (key === "quotes_metadata_timestamp") from the isTransientLocalStorageKey
function and keep the other explicit weather-related keys unchanged; update any
surrounding comments or tests if they assumed a separate equality check.
scripts/backup-restore.js (1)

143-152: cloudLastAutoBackupAt is written twice per successful automatic backup.

uploadSnapshotToWebDAV already sets STORAGE_KEYS.cloudLastAutoBackupAt at line 149 when isAutomatic is true, and then maybeRunAutomaticBackup sets it again at line 315. Harmless, but redundant — drop one of them (probably the one in maybeRunAutomaticBackup, so the timestamp reflects upload completion consistently).

Also applies to: 302-317

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/backup-restore.js` around lines 143 - 152, Remove the redundant write
to STORAGE_KEYS.cloudLastAutoBackupAt so the timestamp is only set when the
upload actually completes; specifically, keep the setLocalStorage call inside
uploadSnapshotToWebDAV (which runs when isAutomatic is true) and remove the
duplicate localStorage.setItem call in maybeRunAutomaticBackup (the block that
currently sets cloudLastAutoBackupAt around lines 302–317), ensuring only
uploadSnapshotToWebDAV updates the key to reflect successful upload completion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@index.html`:
- Around line 1867-1872: The WebDAV inputs (webdavUrlInput, webdavUsernameInput,
webdavPasswordInput) lack accessible labels; add <label> elements associated to
each input (using for="webdavUrlInput", for="webdavUsernameInput",
for="webdavPasswordInput") and use the same visible-or-visually-hidden label
pattern as editBookmarkName/editBookmarkURL so screen readers get proper labels
while preserving the existing placeholders; ensure the labels provide
descriptive text (e.g., "WebDAV URL", "Username (optional)", "Password or app
password (optional)").
- Line 1859: The Cloud Backup UI fails to translate because
scripts/backup-restore.js uses non-matching keys: update the assignment for
element id "#cloudBackupSectionTitle" in scripts/backup-restore.js (where
t("backupModuleTitle") is used) to t("cloudBackupSectionTitle"), and replace
t("cloudAutoBackupHint") with an existing locale key or add a new
"cloudAutoBackupHint" entry to all locale files (locales/*.js) so keys are
consistent; also open locales/en.js and remove the duplicated webdav entries
(keep a single set for webdavTitle, webdavBackupText, webdavRestoreText,
webdavUrlPlaceholder) ensuring the retained webdavRestoreText value is the
intended one across all locales.

In `@locales/el.js`:
- Around line 198-217: Add the missing "cloudAutoBackupHint" and
"cloudAutoBackupInvalidInterval" keys to the locales/el.js translations (the
same change should be applied to the other locale files noted), providing Greek
strings for the auto-backup toggle description and the alert when the interval
is below 1 hour; update the same translation object where "cloudAutoBackupText"
and related webdav keys live so the keys are present when
scripts/backup-restore.js looks them up.

In `@locales/en.js`:
- Around line 208-243: Remove the stale duplicate WebDAV entries (the earlier
block defining webdavTitle, webdavBackupText, webdavRestoreText,
webdavUrlPlaceholder, webdavUsernamePlaceholder, webdavPasswordPlaceholder,
webdavMissingConfig, webdavPermissionDenied, webdavBackupCompleted,
webdavDownloadFailed, webdavUploadFailed, webdavRestoreConfirm and the obsolete
webdavFileNamePlaceholder) so only the correct cloudBackupSection block remains;
then add the three missing locale keys used by scripts/backup-restore.js —
backupModuleTitle, cloudAutoBackupHint, and cloudAutoBackupInvalidInterval — (or
alternatively change the t(...) calls in backup-restore.js/applyStorageTexts()
to use the existing cloudBackupSectionTitle, cloudAutoBackupText and
cloudIntervalInvalid key names), ensuring the keys referenced in
applyStorageTexts() and by the UI elements (`#cloudBackupSectionTitle`,
`#cloudAutoBackupHint` and the invalid interval alert) match the locale file.

In `@manifest`(firefox).json:
- Around line 15-18: Remove the broad "http://*/*" and "https://*/*" entries
from the manifest's optional_permissions array and instead request precise
origins at runtime: keep only genuinely static optional permissions in
optional_permissions, and when the user supplies a WebDAV URL construct a
specific origin pattern (e.g., "https://example.com/*") and call
browser.permissions.request({origins: [constructedOrigin]}) to obtain access;
update any code that assumes the wildcard (search for optional_permissions and
any permissions.request usage) to build and request the specific origin from the
user-supplied URL before attempting WebDAV operations.

In `@scripts/backup-restore.js`:
- Around line 257-261: The code is persisting the WebDAV password in plaintext
via localStorage.setItem(STORAGE_KEYS.webdavPassword,
webdavPasswordInput.value); change this so credentials are not page-accessible:
when persisting, use chrome.storage.local (extension-isolated) instead of
localStorage for STORAGE_KEYS.webdavPassword and related WebDAV fields, and if
there's a "remember" toggle implement session-only storage (sessionStorage) when
not remembered; update any save logic around webdavUsernameInput.value,
webdavPasswordInput.value and cloudAutoBackupCheckbox to use the appropriate
storage API and ensure retrieval code reads from
chrome.storage.local/sessionStorage accordingly, and add a brief UI notice near
the WebDAV input warning users about the risk and recommending an app password.
- Around line 267-279: getWebDAVConfig currently calls new URL(baseUrl).origin
which can throw for malformed user input and surface as an upload failure;
modify getWebDAVConfig to validate/parse baseUrl inside a try/catch (or use a
safe absolute-URL check) and if parsing fails return null so callers (e.g.,
uploadSnapshotToWebDAV) treat it as missing config; ensure the returned object
still contains baseUrl, username, password and a safe requestOrigin only when
URL parsing succeeds.
- Around line 217-230: The translations use nonexistent locale keys
(backupModuleTitle, cloudAutoBackupHint, cloudAutoBackupInvalidInterval) causing
silent fallbacks; update the calls in applyStorageTexts (and the
saveBackupConfig usage) to the existing locale keys defined in your locales (or
alternatively add these three keys to every locales/*.js), i.e., change
t("backupModuleTitle") and t("cloudAutoBackupHint") in applyStorageTexts and
t("cloudAutoBackupInvalidInterval") in saveBackupConfig to match the established
keys in en.js so the UI respects the selected language.

In `@scripts/snapshot-service.js`:
- Around line 119-151: The exportObjectStore function can hang because
store.getAllKeys() and store.get(key) lack error handlers; add request.onerror
handlers for the getAllKeys() request to reject with its error, and for each
store.get(key) to reject on failure (referencing exportObjectStore,
store.getAllKeys, and the inner store.get loop), ensuring pending is
decremented/short-circuited appropriately if needed; keep the existing
transaction.onerror but ensure any rejection clears outstanding callbacks so the
returned Promise always resolves or rejects, and still await
serializeIndexedDBValue(result) inside the successful get handler.

In `@style.css`:
- Around line 4073-4079: The .cloudMethodInlinePicker rule uses an undefined CSS
variable --lightColor-blue so its background becomes transparent; update the
background-color to a valid token (e.g. --bg-color-blue or
--accentLightTint-blue) or remove the background-color declaration if no fill is
desired; modify the .cloudMethodInlinePicker selector in the stylesheet to
reference the chosen existing variable (instead of --lightColor-blue) and verify
the visual result in the UI.

---

Outside diff comments:
In `@scripts/languages.js`:
- Around line 244-256: Locale key cloudPrefixPlaceholder is defined but unused;
either remove it from all locale files or wire it into the UI by adding a
corresponding input in index.html and mapping it in scripts/languages.js's
placeholderMap. To implement the feature: add an input element for the cloud
prefix in index.html with an id (e.g., "cloudPrefixInput"), then add { id:
"cloudPrefixInput", key: "cloudPrefixPlaceholder" } to the placeholderMap array
in scripts/languages.js so loadPlaceholders/getPlaceholder logic applies;
alternatively, delete the cloudPrefixPlaceholder entries from all locale JSONs
if the feature is not needed.

---

Nitpick comments:
In `@CHANGELOG.md`:
- Line 21: Update the CHANGELOG entry that currently reads "Added WebDAV backup
and restore support, including manual cloud backup and restore for MYNT
settings." to include the author and PR attribution in the same format as other
entries (e.g., "([`@author`]) ([`#PR`])") and extend the text to mention automatic
scheduled backups support (e.g., "...including manual and automatic scheduled
cloud backups and restore for MYNT settings."), keeping punctuation and style
consistent with other [Unreleased] → Added items.

In `@index.html`:
- Around line 1897-1898: The number input with id "cloudIntervalInput" (class
"webdavInput webdavIntervalInput") currently has min="1" but no upper bound; add
a sensible max (e.g., max="720") to the input and enforce the same limit in any
client-side validation logic that reads/sets this field (validate in the form
submit handler or the function that processes cloudIntervalInput to clamp or
reject values > max), and update any placeholder/help text if necessary to
reflect the allowed range.
- Around line 1871-1872: The password input with id "webdavPasswordInput" is
missing an autocomplete hint; add autocomplete="current-password" to that
element and also add autocomplete="username" to the corresponding username input
(the WebDAV username input element, e.g., the element with id like
"webdavUsernameInput" or the form's username input) so browsers and password
managers can store/fill credentials correctly (or use autocomplete="off" on both
if you intentionally want to disable saving).

In `@locales/fa.js`:
- Around line 224-243: Change the newly added quoted object keys to the unquoted
style used elsewhere in the file: replace "cloudBackupSectionTitle",
"webdavTitle", "webdavBackupText", "webdavRestoreText", "webdavUrlPlaceholder",
"cloudPrefixPlaceholder", "webdavUsernamePlaceholder",
"webdavPasswordPlaceholder", "cloudAutoBackupText", "cloudIntervalPlaceholder",
"cloudIntervalHours", "saveBackupConfig", "backupConfigSaved",
"webdavMissingConfig", "webdavPermissionDenied", "webdavBackupCompleted",
"webdavDownloadFailed", "webdavUploadFailed", "webdavRestoreConfirm", and
"webdavLatestPointerMissing" so they appear without surrounding quotes (e.g.,
cloudBackupSectionTitle:) and preserve the exact string values and commas to
keep the object valid.

In `@manifest.json`:
- Around line 8-15: The manifest currently declares both broad wildcards in
optional_host_permissions and redundant specific origins (the
google/duckduckgo/brave/wikipedia endpoints); choose one approach and update
optional_host_permissions accordingly: either keep the wildcards (http://*/* and
https://*/*) and remove the specific endpoint entries to simplify the manifest,
or remove the global wildcards and keep only the necessary specific origins and
handle the WebDAV origin at runtime by calling permissions.request({ origins:
[...] }) via the existing ensureHostPermission logic in
scripts/backup-restore.js so you don't require full-web optional grants.

In `@scripts/backup-restore.js`:
- Around line 143-152: Remove the redundant write to
STORAGE_KEYS.cloudLastAutoBackupAt so the timestamp is only set when the upload
actually completes; specifically, keep the setLocalStorage call inside
uploadSnapshotToWebDAV (which runs when isAutomatic is true) and remove the
duplicate localStorage.setItem call in maybeRunAutomaticBackup (the block that
currently sets cloudLastAutoBackupAt around lines 302–317), ensuring only
uploadSnapshotToWebDAV updates the key to reflect successful upload completion.

In `@scripts/snapshot-service.js`:
- Around line 196-212: The openDatabase promise currently rejects with a generic
Error in request.onerror, losing diagnostic info; change request.onerror to
reject with the underlying IndexedDB error (use request.error or
event.target.error) so callers (e.g., webdavUploadFailed/restorefailed) get the
real cause, and add a request.onblocked handler that rejects or rejects with a
specific "blocked" Error (or logs and rejects) to surface upgrade blocking
conditions; locate these handlers in the openDatabase function (request.onerror,
request.onblocked) and update them accordingly.
- Around line 214-221: isTransientLocalStorageKey contains a redundant check:
key.startsWith("quotes_") already covers "quotes_metadata_timestamp", so remove
the explicit equality branch (key === "quotes_metadata_timestamp") from the
isTransientLocalStorageKey function and keep the other explicit weather-related
keys unchanged; update any surrounding comments or tests if they assumed a
separate equality check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5250ce54-5d3d-42f4-b3ee-0bf6fd0626e6

📥 Commits

Reviewing files that changed from the base of the PR and between dc4519c and e653381.

📒 Files selected for processing (39)
  • CHANGELOG.md
  • index.html
  • locales/ar_SA.js
  • locales/az.js
  • locales/bn.js
  • locales/cs.js
  • locales/de.js
  • locales/el.js
  • locales/en.js
  • locales/es.js
  • locales/fa.js
  • locales/fr.js
  • locales/hi.js
  • locales/hu.js
  • locales/idn.js
  • locales/it.js
  • locales/ja.js
  • locales/ko.js
  • locales/mr.js
  • locales/np.js
  • locales/pl.js
  • locales/pt.js
  • locales/ru.js
  • locales/sl.js
  • locales/ta.js
  • locales/th.js
  • locales/tr.js
  • locales/uk.js
  • locales/ur.js
  • locales/uz.js
  • locales/vi.js
  • locales/zh.js
  • locales/zh_TW.js
  • manifest(firefox).json
  • manifest.json
  • scripts/backup-restore.js
  • scripts/languages.js
  • scripts/snapshot-service.js
  • style.css

Comment thread index.html
<div class="section expanded">
<div class="sectionOuter">
<div class="sectionHeader" role="button">
<span class="sectionTitle" id="cloudBackupSectionTitle">Cloud Backup</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the missing/mismatched keys
rg -nP '\b(backupModuleTitle|cloudAutoBackupHint|cloudBackupSectionTitle)\b' --type=js --type=html
echo "---"
# Show en.js duplicates for webdav* keys
rg -nP '"(webdavTitle|webdavBackupText|webdavRestoreText|webdavUrlPlaceholder)"\s*:' locales/en.js

Repository: prem-k-r/MaterialYouNewTab

Length of output: 3406


Translation key mismatches prevent Cloud Backup section from displaying properly.

The code in scripts/backup-restore.js (lines 218 and 223) attempts to translate elements using keys that either don't exist or don't match the locale files:

  1. Line 218 sets #cloudBackupSectionTitle using t("backupModuleTitle"), but backupModuleTitle is not defined in any locale file. All 28 locale files define cloudBackupSectionTitle instead.

  2. Line 223 sets #cloudAutoBackupHint using t("cloudAutoBackupHint"), but this key is missing from all locale files entirely.

Additionally, locales/en.js contains duplicate entries for WebDAV keys:

  • Lines 208–211 define webdavTitle, webdavBackupText, webdavRestoreText ("Restore from WebDAV"), and webdavUrlPlaceholder
  • Lines 225–228 redefine the same keys with conflicting webdavRestoreText value ("Restore Latest")

Align the translation key names between scripts/backup-restore.js and all locale files (locales/*.js). Either:

  • Change line 218 to use t("cloudBackupSectionTitle") and line 223 to use an existing key, or
  • Add backupModuleTitle and cloudAutoBackupHint definitions to all 28 locale files

Remove duplicate webdav entries in locales/en.js and keep one consistent set.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.html` at line 1859, The Cloud Backup UI fails to translate because
scripts/backup-restore.js uses non-matching keys: update the assignment for
element id "#cloudBackupSectionTitle" in scripts/backup-restore.js (where
t("backupModuleTitle") is used) to t("cloudBackupSectionTitle"), and replace
t("cloudAutoBackupHint") with an existing locale key or add a new
"cloudAutoBackupHint" entry to all locale files (locales/*.js) so keys are
consistent; also open locales/en.js and remove the duplicated webdav entries
(keep a single set for webdavTitle, webdavBackupText, webdavRestoreText,
webdavUrlPlaceholder) ensuring the retained webdavRestoreText value is the
intended one across all locales.

Comment thread index.html
Comment on lines +1867 to +1872
<input type="url" id="webdavUrlInput" class="webdavInput"
placeholder="https://example.com/remote.php/dav/files/username/backups">
<input type="text" id="webdavUsernameInput" class="webdavInput"
placeholder="Username (optional)">
<input type="password" id="webdavPasswordInput" class="webdavInput"
placeholder="Password or app password (optional)">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing <label> elements for WebDAV inputs.

The URL, username, and password fields rely solely on placeholder text. Placeholders aren't accessible labels — screen readers may not announce them and the fields have no visible label text after the user starts typing. Consider adding visually-associated (or visually-hidden but programmatically-associated) <label> elements, matching the pattern used for editBookmarkName/editBookmarkURL elsewhere in this file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.html` around lines 1867 - 1872, The WebDAV inputs (webdavUrlInput,
webdavUsernameInput, webdavPasswordInput) lack accessible labels; add <label>
elements associated to each input (using for="webdavUrlInput",
for="webdavUsernameInput", for="webdavPasswordInput") and use the same
visible-or-visually-hidden label pattern as editBookmarkName/editBookmarkURL so
screen readers get proper labels while preserving the existing placeholders;
ensure the labels provide descriptive text (e.g., "WebDAV URL", "Username
(optional)", "Password or app password (optional)").

Comment thread locales/el.js
Comment on lines +198 to +217
"cloudBackupSectionTitle": "Αντίγραφο ασφαλείας cloud",
"webdavTitle": "Συγχρονισμός WebDAV",
"webdavBackupText": "Δημιουργία αντιγράφου στο WebDAV",
"webdavRestoreText": "Επαναφορά τελευταίου",
"webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
"cloudPrefixPlaceholder": "MYNT_Backup",
"webdavUsernamePlaceholder": "Όνομα χρήστη (προαιρετικό)",
"webdavPasswordPlaceholder": "Κωδικός ή κωδικός εφαρμογής (προαιρετικό)",
"cloudAutoBackupText": "Ενεργοποίηση αυτόματου αντιγράφου ασφαλείας",
"cloudIntervalPlaceholder": "Ώρες",
"cloudIntervalHours": "Ώρες",
"saveBackupConfig": "Αποθήκευση ρυθμίσεων αντιγράφου ασφαλείας",
"backupConfigSaved": "Οι ρυθμίσεις αντιγράφου ασφαλείας αποθηκεύτηκαν.",
"webdavMissingConfig": "Συμπληρώστε πρώτα το URL του φακέλου WebDAV.",
"webdavPermissionDenied": "Δεν δόθηκε άδεια host για αυτόν τον διακομιστή WebDAV.",
"webdavBackupCompleted": "Το αντίγραφο ασφαλείας μεταφορτώθηκε επιτυχώς στο WebDAV!",
"webdavDownloadFailed": "Αποτυχία λήψης αντιγράφου ασφαλείας από το WebDAV: ",
"webdavUploadFailed": "Αποτυχία μεταφόρτωσης αντιγράφου ασφαλείας στο WebDAV: ",
"webdavRestoreConfirm": "Επαναφορά ρυθμίσεων από το πιο πρόσφατο αντίγραφο ασφαλείας WebDAV; Τα τρέχοντα τοπικά δεδομένα θα αντικατασταθούν.",
"webdavLatestPointerMissing": "Δεν βρέθηκε εγγραφή του πιο πρόσφατου αντιγράφου ασφαλείας στον φάκελο MYNT."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing cloudAutoBackupHint and cloudAutoBackupInvalidInterval translations.

These two keys are surfaced to users by scripts/backup-restore.js (the auto-backup toggle description and the alert when the interval is below 1 hour), but they’re not present in this locale. Greek users will see the English fallback for both. Please add Greek equivalents — same applies to locales/ru.js, locales/np.js, and the other 23 locale files touched by this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@locales/el.js` around lines 198 - 217, Add the missing "cloudAutoBackupHint"
and "cloudAutoBackupInvalidInterval" keys to the locales/el.js translations (the
same change should be applied to the other locale files noted), providing Greek
strings for the auto-backup toggle description and the alert when the interval
is below 1 hour; update the same translation object where "cloudAutoBackupText"
and related webdav keys live so the keys are present when
scripts/backup-restore.js looks them up.

Comment thread locales/en.js
Comment on lines +208 to +243
"webdavTitle": "WebDAV Sync",
"webdavBackupText": "Backup to WebDAV",
"webdavRestoreText": "Restore from WebDAV",
"webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
"webdavFileNamePlaceholder": "mynt-backup.json",
"webdavUsernamePlaceholder": "Username (optional)",
"webdavPasswordPlaceholder": "Password or app password (optional)",
"webdavMissingConfig": "Please fill in the WebDAV URL and file name first.",
"webdavPermissionDenied": "Host permission was not granted for this WebDAV server.",
"webdavBackupCompleted": "Backup uploaded to WebDAV successfully!",
"webdavDownloadFailed": "Failed to download backup from WebDAV: ",
"webdavUploadFailed": "Failed to upload backup to WebDAV: ",
"webdavRestoreConfirm": "Restore settings from WebDAV? Your current local data will be overwritten.",
"deleteBookmark": "Are you sure you want to delete the bookmark \"{title}\"?", // Do not translate {title}
"UnsupportedBrowser": "Bookmarks are not supported in your browser.",
"resetShortcutsPrompt": "All saved shortcuts will be deleted and reset to default. Do you want to continue?"
};
"resetShortcutsPrompt": "All saved shortcuts will be deleted and reset to default. Do you want to continue?",
"cloudBackupSectionTitle": "Cloud Backup",
"webdavTitle": "WebDAV Sync",
"webdavBackupText": "Backup to WebDAV",
"webdavRestoreText": "Restore Latest",
"webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
"cloudPrefixPlaceholder": "MYNT_Backup",
"webdavUsernamePlaceholder": "Username (optional)",
"webdavPasswordPlaceholder": "Password or app password (optional)",
"cloudAutoBackupText": "Enable automatic backup",
"cloudIntervalPlaceholder": "Hours",
"cloudIntervalHours": "Hours",
"saveBackupConfig": "Save Backup Config",
"backupConfigSaved": "Backup configuration saved.",
"webdavMissingConfig": "Please fill in the WebDAV folder URL first.",
"webdavPermissionDenied": "Host permission was not granted for this WebDAV server.",
"webdavBackupCompleted": "Backup uploaded to WebDAV successfully!",
"webdavDownloadFailed": "Failed to download backup from WebDAV: ",
"webdavUploadFailed": "Failed to upload backup to WebDAV: ",
"webdavRestoreConfirm": "Restore settings from the latest WebDAV backup? Your current local data will be overwritten.",
"webdavLatestPointerMissing": "No latest backup record was found in the MYNT folder."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove duplicate WebDAV keys and add the missing translation entries.

Biome flags that webdavTitle, webdavBackupText, webdavRestoreText, webdavUrlPlaceholder, webdavUsernamePlaceholder, webdavPasswordPlaceholder, webdavMissingConfig, webdavPermissionDenied, webdavBackupCompleted, webdavDownloadFailed, webdavUploadFailed, and webdavRestoreConfirm are all defined twice (lines 208‑220 are dead, overwritten at 225‑242). The stale block also keeps obsolete keys webdavFileNamePlaceholder that no longer correspond to any UI element.

Additionally, scripts/backup-restore.js references three translation keys that are not defined anywhere in the locales (only in storageFallbackTexts):

  • backupModuleTitle — applied to #cloudBackupSectionTitle at applyStorageTexts(). The locale key you actually defined here is cloudBackupSectionTitle, so this will always fall back to the English default even in other languages.
  • cloudAutoBackupHint — applied to #cloudAutoBackupHint.
  • cloudAutoBackupInvalidInterval — shown via alertPrompt when the auto-backup interval is invalid.

Either rename the t(...) calls in backup-restore.js to match the existing locale keys, or add these three keys to en.js (and to every other locale file). Right now three user-facing strings will never localize, which defeats the purpose of the locale updates in this PR.

🔧 Proposed cleanup
-    "webdavTitle": "WebDAV Sync",
-    "webdavBackupText": "Backup to WebDAV",
-    "webdavRestoreText": "Restore from WebDAV",
-    "webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
-    "webdavFileNamePlaceholder": "mynt-backup.json",
-    "webdavUsernamePlaceholder": "Username (optional)",
-    "webdavPasswordPlaceholder": "Password or app password (optional)",
-    "webdavMissingConfig": "Please fill in the WebDAV URL and file name first.",
-    "webdavPermissionDenied": "Host permission was not granted for this WebDAV server.",
-    "webdavBackupCompleted": "Backup uploaded to WebDAV successfully!",
-    "webdavDownloadFailed": "Failed to download backup from WebDAV: ",
-    "webdavUploadFailed": "Failed to upload backup to WebDAV: ",
-    "webdavRestoreConfirm": "Restore settings from WebDAV? Your current local data will be overwritten.",
     "deleteBookmark": "Are you sure you want to delete the bookmark \"{title}\"?",
     "UnsupportedBrowser": "Bookmarks are not supported in your browser.",
     "resetShortcutsPrompt": "All saved shortcuts will be deleted and reset to default. Do you want to continue?",
     "cloudBackupSectionTitle": "Cloud Backup",
+    "cloudAutoBackupHint": "Back up settings to WebDAV on a schedule",
+    "cloudAutoBackupInvalidInterval": "Automatic backup interval must be at least 1 hour.",
     "webdavTitle": "WebDAV Sync",

…and in scripts/backup-restore.js:

-    document.getElementById("cloudBackupSectionTitle").textContent = t("backupModuleTitle");
+    document.getElementById("cloudBackupSectionTitle").textContent = t("cloudBackupSectionTitle");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"webdavTitle": "WebDAV Sync",
"webdavBackupText": "Backup to WebDAV",
"webdavRestoreText": "Restore from WebDAV",
"webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
"webdavFileNamePlaceholder": "mynt-backup.json",
"webdavUsernamePlaceholder": "Username (optional)",
"webdavPasswordPlaceholder": "Password or app password (optional)",
"webdavMissingConfig": "Please fill in the WebDAV URL and file name first.",
"webdavPermissionDenied": "Host permission was not granted for this WebDAV server.",
"webdavBackupCompleted": "Backup uploaded to WebDAV successfully!",
"webdavDownloadFailed": "Failed to download backup from WebDAV: ",
"webdavUploadFailed": "Failed to upload backup to WebDAV: ",
"webdavRestoreConfirm": "Restore settings from WebDAV? Your current local data will be overwritten.",
"deleteBookmark": "Are you sure you want to delete the bookmark \"{title}\"?", // Do not translate {title}
"UnsupportedBrowser": "Bookmarks are not supported in your browser.",
"resetShortcutsPrompt": "All saved shortcuts will be deleted and reset to default. Do you want to continue?"
};
"resetShortcutsPrompt": "All saved shortcuts will be deleted and reset to default. Do you want to continue?",
"cloudBackupSectionTitle": "Cloud Backup",
"webdavTitle": "WebDAV Sync",
"webdavBackupText": "Backup to WebDAV",
"webdavRestoreText": "Restore Latest",
"webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
"cloudPrefixPlaceholder": "MYNT_Backup",
"webdavUsernamePlaceholder": "Username (optional)",
"webdavPasswordPlaceholder": "Password or app password (optional)",
"cloudAutoBackupText": "Enable automatic backup",
"cloudIntervalPlaceholder": "Hours",
"cloudIntervalHours": "Hours",
"saveBackupConfig": "Save Backup Config",
"backupConfigSaved": "Backup configuration saved.",
"webdavMissingConfig": "Please fill in the WebDAV folder URL first.",
"webdavPermissionDenied": "Host permission was not granted for this WebDAV server.",
"webdavBackupCompleted": "Backup uploaded to WebDAV successfully!",
"webdavDownloadFailed": "Failed to download backup from WebDAV: ",
"webdavUploadFailed": "Failed to upload backup to WebDAV: ",
"webdavRestoreConfirm": "Restore settings from the latest WebDAV backup? Your current local data will be overwritten.",
"webdavLatestPointerMissing": "No latest backup record was found in the MYNT folder."
"deleteBookmark": "Are you sure you want to delete the bookmark \"{title}\"?", // Do not translate {title}
"UnsupportedBrowser": "Bookmarks are not supported in your browser.",
"resetShortcutsPrompt": "All saved shortcuts will be deleted and reset to default. Do you want to continue?",
"cloudBackupSectionTitle": "Cloud Backup",
"cloudAutoBackupHint": "Back up settings to WebDAV on a schedule",
"cloudAutoBackupInvalidInterval": "Automatic backup interval must be at least 1 hour.",
"webdavTitle": "WebDAV Sync",
"webdavBackupText": "Backup to WebDAV",
"webdavRestoreText": "Restore Latest",
"webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
"cloudPrefixPlaceholder": "MYNT_Backup",
"webdavUsernamePlaceholder": "Username (optional)",
"webdavPasswordPlaceholder": "Password or app password (optional)",
"cloudAutoBackupText": "Enable automatic backup",
"cloudIntervalPlaceholder": "Hours",
"cloudIntervalHours": "Hours",
"saveBackupConfig": "Save Backup Config",
"backupConfigSaved": "Backup configuration saved.",
"webdavMissingConfig": "Please fill in the WebDAV folder URL first.",
"webdavPermissionDenied": "Host permission was not granted for this WebDAV server.",
"webdavBackupCompleted": "Backup uploaded to WebDAV successfully!",
"webdavDownloadFailed": "Failed to download backup from WebDAV: ",
"webdavUploadFailed": "Failed to upload backup to WebDAV: ",
"webdavRestoreConfirm": "Restore settings from the latest WebDAV backup? Your current local data will be overwritten.",
"webdavLatestPointerMissing": "No latest backup record was found in the MYNT folder."
🧰 Tools
🪛 Biome (2.4.11)

[error] 208-208: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 209-209: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 210-210: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 211-211: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 213-213: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 214-214: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 215-215: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 216-216: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 217-217: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 218-218: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 219-219: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)


[error] 220-220: This property is later overwritten by an object member with the same name.

(lint/suspicious/noDuplicateObjectKeys)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@locales/en.js` around lines 208 - 243, Remove the stale duplicate WebDAV
entries (the earlier block defining webdavTitle, webdavBackupText,
webdavRestoreText, webdavUrlPlaceholder, webdavUsernamePlaceholder,
webdavPasswordPlaceholder, webdavMissingConfig, webdavPermissionDenied,
webdavBackupCompleted, webdavDownloadFailed, webdavUploadFailed,
webdavRestoreConfirm and the obsolete webdavFileNamePlaceholder) so only the
correct cloudBackupSection block remains; then add the three missing locale keys
used by scripts/backup-restore.js — backupModuleTitle, cloudAutoBackupHint, and
cloudAutoBackupInvalidInterval — (or alternatively change the t(...) calls in
backup-restore.js/applyStorageTexts() to use the existing
cloudBackupSectionTitle, cloudAutoBackupText and cloudIntervalInvalid key
names), ensuring the keys referenced in applyStorageTexts() and by the UI
elements (`#cloudBackupSectionTitle`, `#cloudAutoBackupHint` and the invalid
interval alert) match the locale file.

Comment thread manifest(firefox).json
Comment on lines +15 to +18
"optional_permissions": [
"http://*/*",
"https://*/*"
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Firefox AMO review policy optional_permissions http://*/* wildcard host permissions user-provided URLs

💡 Result:

Firefox AMO review policy requires add-ons to "only request those permissions that are necessary for them to function" (Mozilla Add-on Policies). Broad host permissions like http:/// (equivalent to <all_urls>) are permitted if justified by the extension's core functionality, but reviewers scrutinize them closely during human review to ensure minimal necessary scope. Optional permissions (via optional_permissions in Manifest V2 or optional_host_permissions in V3+) allow requesting host permissions like http:/// at runtime using browser.permissions.request({origins: ['<all_urls>']}), prompting users for "Access your data for all websites". Users can manage these in about:addons. Reviewers evaluate if runtime requests align with described functionality and privacy practices; unjustified broad optional permissions risk rejection. For user-provided URLs, extensions should request specific narrow host patterns at runtime (e.g., origins: ['http://example.com/*']) rather than broad wildcards, minimizing scope per policy emphasis on least privilege. No explicit ban on wildcard optional_permissions found, but documentation advises avoiding <all_urls> where possible (e.g., use activeTab).

Citations:


🏁 Script executed:

# Explore repository structure to understand the extension's purpose and context
git ls-files | head -30

Repository: prem-k-r/MaterialYouNewTab

Length of output: 664


🏁 Script executed:

# Look for manifest files and documentation
find . -type f \( -name "manifest*.json" -o -name "README*" -o -name "*.md" \) | grep -v node_modules

Repository: prem-k-r/MaterialYouNewTab

Length of output: 251


🏁 Script executed:

# Read the Firefox manifest file to understand the extension
cat -n manifest.firefox.json | head -50

Repository: prem-k-r/MaterialYouNewTab

Length of output: 123


🏁 Script executed:

# Search for WebDAV-related code or comments
rg -i "webdav" --max-count 20

Repository: prem-k-r/MaterialYouNewTab

Length of output: 40107


🏁 Script executed:

# Look for any AMO review notes or comments about permissions
rg -i "amo|review|permission" --max-count 15

Repository: prem-k-r/MaterialYouNewTab

Length of output: 12269


🏁 Script executed:

# Read the Firefox manifest file (with parentheses in filename)
cat -n "manifest(firefox).json"

Repository: prem-k-r/MaterialYouNewTab

Length of output: 1362


🏁 Script executed:

# Check README for WebDAV documentation
rg -i "webdav|permission|backup" README.md -A 2 -B 2

Repository: prem-k-r/MaterialYouNewTab

Length of output: 632


Remove broad http://*/* + https://*/* from optional_permissions; request narrower origins at runtime instead.

Firefox AMO policy requires minimal permission scope, even for optional permissions. Declaring broad wildcards in the manifest—even when narrowed at runtime via permissions.request()—risks rejection during review because the manifest itself signals overly broad requests to reviewers.

Since WebDAV URLs are user-supplied at runtime, construct specific origins from the user's configured URL and request only those (e.g., origins: ['https://user-domain.com/*']) instead of pre-declaring http://*/* and https://*/*. This approach:

  • Demonstrates least-privilege compliance in the manifest itself
  • Aligns with Mozilla's guidance for user-provided endpoints
  • Avoids needing explicit AMO justification for full-web wildcards
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@manifest`(firefox).json around lines 15 - 18, Remove the broad "http://*/*"
and "https://*/*" entries from the manifest's optional_permissions array and
instead request precise origins at runtime: keep only genuinely static optional
permissions in optional_permissions, and when the user supplies a WebDAV URL
construct a specific origin pattern (e.g., "https://example.com/*") and call
browser.permissions.request({origins: [constructedOrigin]}) to obtain access;
update any code that assumes the wildcard (search for optional_permissions and
any permissions.request usage) to build and request the specific origin from the
user-supplied URL before attempting WebDAV operations.

Comment thread scripts/backup-restore.js
Comment on lines +217 to 230
function applyStorageTexts() {
document.getElementById("cloudBackupSectionTitle").textContent = t("backupModuleTitle");
document.getElementById("webdavTitle").textContent = t("webdavTitle");
document.getElementById("webdavBackupText").textContent = t("webdavBackupText");
document.getElementById("webdavRestoreText").textContent = t("webdavRestoreText");
document.getElementById("cloudAutoBackupText").textContent = t("cloudAutoBackupText");
document.getElementById("cloudAutoBackupHint").textContent = t("cloudAutoBackupHint");
document.getElementById("cloudIntervalUnitLabel").textContent = t("cloudIntervalHours");
saveBackupConfigBtn.textContent = t("saveBackupConfig");
webdavUrlInput.placeholder = t("webdavUrlPlaceholder");
webdavUsernameInput.placeholder = t("webdavUsernamePlaceholder");
webdavPasswordInput.placeholder = t("webdavPasswordPlaceholder");
cloudIntervalInput.placeholder = t("cloudIntervalPlaceholder");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Root cause of the missing-translation bug.

t("backupModuleTitle"), t("cloudAutoBackupHint"), and (in saveBackupConfig) t("cloudAutoBackupInvalidInterval") all resolve to keys that are not defined in any locales/*.js. They silently degrade to the English storageFallbackTexts strings, so changing the extension language has no effect on these three UI strings.

Either (preferred) align the key used here with the locale key already defined in en.js:

-    document.getElementById("cloudBackupSectionTitle").textContent = t("backupModuleTitle");
+    document.getElementById("cloudBackupSectionTitle").textContent = t("cloudBackupSectionTitle");

…or add backupModuleTitle, cloudAutoBackupHint, and cloudAutoBackupInvalidInterval to every locale file. A single source-of-truth is safer than keeping duplicated fallbacks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/backup-restore.js` around lines 217 - 230, The translations use
nonexistent locale keys (backupModuleTitle, cloudAutoBackupHint,
cloudAutoBackupInvalidInterval) causing silent fallbacks; update the calls in
applyStorageTexts (and the saveBackupConfig usage) to the existing locale keys
defined in your locales (or alternatively add these three keys to every
locales/*.js), i.e., change t("backupModuleTitle") and t("cloudAutoBackupHint")
in applyStorageTexts and t("cloudAutoBackupInvalidInterval") in saveBackupConfig
to match the established keys in en.js so the UI respects the selected language.

Comment thread scripts/backup-restore.js
Comment on lines +257 to +261
localStorage.setItem(STORAGE_KEYS.webdavUrl, config.baseUrl);
localStorage.setItem(STORAGE_KEYS.webdavUsername, webdavUsernameInput.value);
localStorage.setItem(STORAGE_KEYS.webdavPassword, webdavPasswordInput.value);
localStorage.setItem(STORAGE_KEYS.cloudAutoEnabled, String(cloudAutoBackupCheckbox.checked));
localStorage.setItem(STORAGE_KEYS.cloudIntervalHours, String(intervalHours));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Storing the WebDAV password in plaintext in localStorage is a privacy risk.

localStorage.setItem(STORAGE_KEYS.webdavPassword, webdavPasswordInput.value) persists the WebDAV credentials in clear text. Any script running in the new-tab origin (including compromised extensions sharing the origin, XSS via an injected wallpaper/proxy response, or DevTools snooping by anyone with physical access) can exfiltrate them. App passwords partially mitigate this, but the UI placeholder suggests a plain password is also acceptable.

Consider at minimum:

  • Documenting the risk in the WebDAV UI (e.g., strongly recommend an app password).
  • Moving credentials to chrome.storage.local (extension-isolated) instead of page-accessible localStorage.
  • Optionally, session-only credentials (sessionStorage) when "remember" is off.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/backup-restore.js` around lines 257 - 261, The code is persisting the
WebDAV password in plaintext via
localStorage.setItem(STORAGE_KEYS.webdavPassword, webdavPasswordInput.value);
change this so credentials are not page-accessible: when persisting, use
chrome.storage.local (extension-isolated) instead of localStorage for
STORAGE_KEYS.webdavPassword and related WebDAV fields, and if there's a
"remember" toggle implement session-only storage (sessionStorage) when not
remembered; update any save logic around webdavUsernameInput.value,
webdavPasswordInput.value and cloudAutoBackupCheckbox to use the appropriate
storage API and ensure retrieval code reads from
chrome.storage.local/sessionStorage accordingly, and add a brief UI notice near
the WebDAV input warning users about the risk and recommending an app password.

Comment thread scripts/backup-restore.js
Comment on lines +267 to +279
function getWebDAVConfig() {
const baseUrl = webdavUrlInput.value.trim().replace(/\/+$/, "");
if (!baseUrl) {
return null;
}

store.clear();
const entries = Object.entries(data);
let pending = entries.length;
return {
baseUrl,
username: webdavUsernameInput.value,
password: webdavPasswordInput.value,
requestOrigin: new URL(baseUrl).origin + "/*"
};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

new URL(baseUrl) can throw for user-entered malformed URLs.

If the user enters something that passes the empty check but isn’t a valid absolute URL (e.g., example.com/dav), new URL(baseUrl).origin throws TypeError: Invalid URL. The error propagates up to uploadSnapshotToWebDAV where it surfaces as webdavUploadFailed: Invalid URL, which is confusing — the real cause is configuration, not an upload failure.

Consider wrapping the URL parse and returning null (treated as “missing config”) so the user sees webdavMissingConfig instead:

-    return {
-        baseUrl,
-        username: webdavUsernameInput.value,
-        password: webdavPasswordInput.value,
-        requestOrigin: new URL(baseUrl).origin + "/*"
-    };
+    try {
+        return {
+            baseUrl,
+            username: webdavUsernameInput.value,
+            password: webdavPasswordInput.value,
+            requestOrigin: new URL(baseUrl).origin + "/*"
+        };
+    } catch {
+        return null;
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function getWebDAVConfig() {
const baseUrl = webdavUrlInput.value.trim().replace(/\/+$/, "");
if (!baseUrl) {
return null;
}
store.clear();
const entries = Object.entries(data);
let pending = entries.length;
return {
baseUrl,
username: webdavUsernameInput.value,
password: webdavPasswordInput.value,
requestOrigin: new URL(baseUrl).origin + "/*"
};
}
function getWebDAVConfig() {
const baseUrl = webdavUrlInput.value.trim().replace(/\/+$/, "");
if (!baseUrl) {
return null;
}
try {
return {
baseUrl,
username: webdavUsernameInput.value,
password: webdavPasswordInput.value,
requestOrigin: new URL(baseUrl).origin + "/*"
};
} catch {
return null;
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/backup-restore.js` around lines 267 - 279, getWebDAVConfig currently
calls new URL(baseUrl).origin which can throw for malformed user input and
surface as an upload failure; modify getWebDAVConfig to validate/parse baseUrl
inside a try/catch (or use a safe absolute-URL check) and if parsing fails
return null so callers (e.g., uploadSnapshotToWebDAV) treat it as missing
config; ensure the returned object still contains baseUrl, username, password
and a safe requestOrigin only when URL parsing succeeds.

Comment on lines +119 to +151
async function exportObjectStore(db, storeName) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, "readonly");
const store = transaction.objectStore(storeName);
const data = {};

store.getAllKeys().onsuccess = (keysEvent) => {
const keys = keysEvent.target.result;

if (!keys.length) {
resolve({});
return;
}

let pending = keys.length;
keys.forEach((key) => {
store.get(key).onsuccess = async (getEvent) => {
try {
data[key] = await serializeIndexedDBValue(getEvent.target.result);
pending -= 1;
if (pending === 0) {
resolve(data);
}
} catch (error) {
reject(error);
}
};
});
};

transaction.onerror = () => reject(transaction.error);
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

exportObjectStore can hang if getAllKeys fails.

Only store.getAllKeys().onsuccess and transaction.onerror are handled. If getAllKeys itself fails (request-level error, e.g., store not found after an upgrade), neither handler fires and the outer await never resolves/rejects. Similarly store.get(key) has no onerror.

-        store.getAllKeys().onsuccess = (keysEvent) => {
+        const keysRequest = store.getAllKeys();
+        keysRequest.onerror = () => reject(keysRequest.error);
+        keysRequest.onsuccess = (keysEvent) => {
             ...
-                store.get(key).onsuccess = async (getEvent) => {
+                const getRequest = store.get(key);
+                getRequest.onerror = () => reject(getRequest.error);
+                getRequest.onsuccess = async (getEvent) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/snapshot-service.js` around lines 119 - 151, The exportObjectStore
function can hang because store.getAllKeys() and store.get(key) lack error
handlers; add request.onerror handlers for the getAllKeys() request to reject
with its error, and for each store.get(key) to reject on failure (referencing
exportObjectStore, store.getAllKeys, and the inner store.get loop), ensuring
pending is decremented/short-circuited appropriately if needed; keep the
existing transaction.onerror but ensure any rejection clears outstanding
callbacks so the returned Promise always resolves or rejects, and still await
serializeIndexedDBValue(result) inside the successful get handler.

Comment thread style.css
Comment on lines +4073 to +4079
.cloudMethodInlinePicker {
background-color: var(--lightColor-blue);
border-radius: 22px;
padding: 16px;
display: none;
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.08);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

var(--lightColor-blue) is not defined anywhere.

Only --bg-color-blue, --accentLightTint-blue, --darkerColor-blue, --darkColor-blue, --textColorDark-blue, and --whitishColor-blue are declared in :root. --lightColor-blue does not exist, so background-color resolves to unset/transparent and .cloudMethodInlinePicker renders with no fill when active. If this class isn’t exercised in the current UI flow it may be going unnoticed — please either point it at the correct token or remove the rule.

-	background-color: var(--lightColor-blue);
+	background-color: var(--accentLightTint-blue);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.cloudMethodInlinePicker {
background-color: var(--lightColor-blue);
border-radius: 22px;
padding: 16px;
display: none;
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.08);
}
.cloudMethodInlinePicker {
background-color: var(--accentLightTint-blue);
border-radius: 22px;
padding: 16px;
display: none;
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.08);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@style.css` around lines 4073 - 4079, The .cloudMethodInlinePicker rule uses
an undefined CSS variable --lightColor-blue so its background becomes
transparent; update the background-color to a valid token (e.g. --bg-color-blue
or --accentLightTint-blue) or remove the background-color declaration if no fill
is desired; modify the .cloudMethodInlinePicker selector in the stylesheet to
reference the chosen existing variable (instead of --lightColor-blue) and verify
the visual result in the UI.

@itz-rj-here itz-rj-here added enhancement New feature or request under-review Currently being reviewed. Please wait for feedback. labels Apr 18, 2026
@prem-k-r prem-k-r added prefer-in-experimental under-discussion Active debate or feedback needed. Not ready for implementation until a consensus is reached and removed under-review Currently being reviewed. Please wait for feedback. labels Apr 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
locales/en.js (1)

209-221: ⚠️ Potential issue | 🟠 Major

Remove the stale duplicate WebDAV locale block.

Lines 209-221 are overwritten by the newer Cloud Backup/WebDAV entries at Lines 225-244, and Biome correctly flags these as duplicate object keys. Keeping both blocks also leaves obsolete wording like webdavFileNamePlaceholder and “URL and file name” in the source.

🧹 Proposed cleanup
-    "webdavTitle": "WebDAV Sync",
-    "webdavBackupText": "Backup to WebDAV",
-    "webdavRestoreText": "Restore from WebDAV",
-    "webdavUrlPlaceholder": "https://example.com/remote.php/dav/files/username/backups",
-    "webdavFileNamePlaceholder": "mynt-backup.json",
-    "webdavUsernamePlaceholder": "Username (optional)",
-    "webdavPasswordPlaceholder": "Password or app password (optional)",
-    "webdavMissingConfig": "Please fill in the WebDAV URL and file name first.",
-    "webdavPermissionDenied": "Host permission was not granted for this WebDAV server.",
-    "webdavBackupCompleted": "Backup uploaded to WebDAV successfully!",
-    "webdavDownloadFailed": "Failed to download backup from WebDAV: ",
-    "webdavUploadFailed": "Failed to upload backup from WebDAV: ",
-    "webdavRestoreConfirm": "Restore settings from WebDAV? Your current local data will be overwritten.",
     "deleteBookmark": "Are you sure you want to delete the bookmark \"{title}\"?",  // Do not translate {title}
     "UnsupportedBrowser": "Bookmarks are not supported in your browser.",
     "resetShortcutsPrompt": "All saved shortcuts will be deleted and reset to default. Do you want to continue?",

Also applies to: 225-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@locales/en.js` around lines 209 - 221, Remove the stale duplicate WebDAV
locale block (the early set of keys including webdavTitle, webdavBackupText,
webdavRestoreText, webdavUrlPlaceholder, webdavFileNamePlaceholder,
webdavUsernamePlaceholder, webdavPasswordPlaceholder, webdavMissingConfig,
webdavPermissionDenied, webdavBackupCompleted, webdavDownloadFailed,
webdavUploadFailed, webdavRestoreConfirm) so only the newer Cloud Backup/WebDAV
entries remain; ensure you keep the canonical keyset (the later block around
webdav... keys) and delete the older duplicate to avoid duplicate object keys
and obsolete wording like "file name" and webdavFileNamePlaceholder.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Line 233: Update the flag image tags in the README table to include alt
attributes and correct the Swedish flag URL: change the Swedish flag src from
flagcdn.com/sv.svg to flagcdn.com/se.svg and add alt text for each row's img tag
(e.g. alt="Hungarian flag" for the "Hungarian - Magyar" row, alt="Swedish flag"
for the "Swedish" row, and alt="Ukrainian flag" for the "Ukrainian" row) so the
Hungarian, Swedish, and Ukrainian table rows have proper alt attributes and the
correct Swedish image source.

---

Duplicate comments:
In `@locales/en.js`:
- Around line 209-221: Remove the stale duplicate WebDAV locale block (the early
set of keys including webdavTitle, webdavBackupText, webdavRestoreText,
webdavUrlPlaceholder, webdavFileNamePlaceholder, webdavUsernamePlaceholder,
webdavPasswordPlaceholder, webdavMissingConfig, webdavPermissionDenied,
webdavBackupCompleted, webdavDownloadFailed, webdavUploadFailed,
webdavRestoreConfirm) so only the newer Cloud Backup/WebDAV entries remain;
ensure you keep the canonical keyset (the later block around webdav... keys) and
delete the older duplicate to avoid duplicate object keys and obsolete wording
like "file name" and webdavFileNamePlaceholder.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dc6442e3-b3a7-4920-bfe7-0d86113d53d4

📥 Commits

Reviewing files that changed from the base of the PR and between e653381 and 5eb52a8.

📒 Files selected for processing (18)
  • .github/pull_request_template.md
  • CHANGELOG.md
  • README.md
  • index.html
  • locales/bn.js
  • locales/cs.js
  • locales/en.js
  • locales/hi.js
  • locales/hu.js
  • locales/sv.js
  • locales/uk.js
  • manifest(firefox).json
  • manifest.json
  • scripts/clock.js
  • scripts/languages.js
  • scripts/search.js
  • scripts/weather.js
  • tools/languagesAnalysis.html
✅ Files skipped from review due to trivial changes (7)
  • .github/pull_request_template.md
  • manifest(firefox).json
  • scripts/clock.js
  • locales/sv.js
  • locales/hi.js
  • locales/uk.js
  • locales/cs.js
🚧 Files skipped from review as they are similar to previous changes (5)
  • CHANGELOG.md
  • scripts/languages.js
  • locales/bn.js
  • manifest.json
  • index.html

Comment thread README.md
@prem-k-r prem-k-r removed their assignment Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request prefer-in-experimental under-discussion Active debate or feedback needed. Not ready for implementation until a consensus is reached

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants